home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / CPP / WFC010.ZIP / SRC / NAMDPIPE.CPP < prev    next >
C/C++ Source or Header  |  1995-12-07  |  13KB  |  494 lines

  1. #include <wfc.h>
  2. #pragma hdrstop
  3.  
  4. /*
  5. ** Author: Samuel R. Blackburn
  6. ** CI$: 76300,326
  7. ** Internet: sammy@sed.csc.com
  8. **
  9. ** You can use it any way you like as long as you don't try to sell it.
  10. **
  11. ** Any attempt to sell WFC in source code form must have the permission
  12. ** of the original author. You can produce commercial executables with
  13. ** WFC but you can't sell WFC.
  14. **
  15. ** Copyright, 1995, Samuel R. Blackburn
  16. **
  17. ** $Workfile: $
  18. ** $Revision: $
  19. ** $Modtime: $
  20. */
  21.  
  22. #if defined( _DEBUG )
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #define new DEBUG_NEW
  26. #endif
  27.  
  28. CNamedPipe::CNamedPipe( DWORD _input_buffer_size, DWORD _output_buffer_size )
  29. {
  30.    m_Initialize( _input_buffer_size, _output_buffer_size );
  31. }
  32.  
  33. CNamedPipe::~CNamedPipe()
  34. {
  35.    if ( m_AutomaticallyDelete == TRUE )
  36.    {
  37.       if ( m_PipeHandle != (HANDLE) NULL )
  38.       {
  39.          Close();
  40.       }
  41.    }
  42.  
  43.    if ( m_InputBuffer != (LPVOID) NULL )
  44.    {
  45.       /*
  46.       ** Free our memory
  47.       */
  48.  
  49.       delete [] m_InputBuffer;
  50.  
  51.       m_InputBuffer = (LPVOID) NULL;
  52.       m_InputBufferSize = 0L;
  53.    }
  54.  
  55.    if ( m_OutputBuffer != (LPVOID) NULL )
  56.    {
  57.       /*
  58.       ** Free our memory
  59.       */
  60.  
  61.       delete [] m_OutputBuffer;
  62.  
  63.       m_OutputBuffer = (LPVOID) NULL;
  64.       m_OutputBufferSize = 0L;
  65.    }
  66. }
  67.  
  68. void CNamedPipe::m_Initialize( DWORD _input_buffer_size, DWORD _output_buffer_size )
  69. {
  70.    m_AutomaticallyDelete = TRUE;
  71.    m_ErrorCode           = 0L;
  72.    m_PipeHandle          = INVALID_HANDLE_VALUE;
  73.    m_Timeout             = NMPWAIT_USE_DEFAULT_WAIT;
  74.    m_PipeName.Empty();
  75.  
  76.    m_InputBufferSize  = _input_buffer_size;
  77.    m_OutputBufferSize = _output_buffer_size;
  78.  
  79.    m_InputBuffer  = new BYTE[ m_InputBufferSize  ];
  80.    m_OutputBuffer = new BYTE[ m_OutputBufferSize ];
  81. }
  82.  
  83. #if defined( _DEBUG )
  84.  
  85. void CNamedPipe::Dump( CDumpContext& dump_context ) const
  86. {
  87.    //CDummyFile::Dump( dump_context );
  88.  
  89.    dump_context << "m_AutomaticallyDelete = "      << m_AutomaticallyDelete      << "\n";
  90.    dump_context << "m_PipeHandle = "               << m_PipeHandle               << "\n";
  91.    dump_context << "m_MaximumNumberOfInstances = " << m_MaximumNumberOfInstances << "\n";
  92.    dump_context << "m_InputBufferSize = "          << m_InputBufferSize          << "\n";
  93.    dump_context << "m_OutputBufferSize = "         << m_OutputBufferSize         << "\n";
  94.    dump_context << "m_NumberOfBytesToWrite = "     << m_NumberOfBytesToWrite     << "\n";
  95.    dump_context << "m_NumberOfBytesRead = "        << m_NumberOfBytesRead        << "\n";
  96.    dump_context << "m_Timeout = "                  << m_Timeout                  << "\n";
  97.    dump_context << "m_PipeName = \""               << m_PipeName                 << "\"\n";
  98.    dump_context << "m_FullPipeName is ";
  99.    m_FullPipeName.Dump( dump_context );
  100.    dump_context << "m_PipeState = "                << m_PipeState                << "\n";
  101.    dump_context << "m_NumberOfInstances = "        << m_NumberOfInstances        << "\n";
  102.    dump_context << "m_MaximumNumberOfBytesBeforeRemoteTransmission = "     << m_MaximumNumberOfBytesBeforeRemoteTransmission   << "\n";
  103.    dump_context << "m_MaximumNumberOfMillisecondsBeforeRemoteTransmission = "     << m_MaximumNumberOfMillisecondsBeforeRemoteTransmission   << "\n";
  104.    dump_context << "m_UserNameOfClientProcess = \"" << m_UserNameOfClientProcess << "\"\n";
  105. }
  106.  
  107. #endif // _DEBUG
  108.  
  109. BOOL CNamedPipe::Call( CString& pipe_name, 
  110.                        LPVOID   write_buffer, 
  111.                        DWORD    size_of_write_buffer, 
  112.                        LPVOID   read_buffer, 
  113.                        DWORD    size_of_read_buffer, 
  114.                        DWORD   *address_of_number_of_bytes_read,
  115.                        DWORD    number_of_milliseconds_to_wait )
  116. {
  117.    ASSERT( write_buffer != NULL );
  118.    ASSERT( read_buffer  != NULL );
  119.  
  120.    if ( write_buffer == NULL || read_buffer == NULL )
  121.    {
  122.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  123.       return( FALSE );
  124.    }
  125.  
  126.    /*
  127.    ** Writes to the pipe then reads from it
  128.    */
  129.  
  130.    BOOL return_value = FALSE;
  131.  
  132.    return_value = ::CallNamedPipe( pipe_name, 
  133.                                    write_buffer,
  134.                                    size_of_write_buffer,
  135.                                    read_buffer,
  136.                                    size_of_read_buffer,
  137.                                    address_of_number_of_bytes_read,
  138.                                    number_of_milliseconds_to_wait );
  139.  
  140.    if ( return_value == TRUE )
  141.    {
  142.       return( TRUE );
  143.    }
  144.    else
  145.    {
  146.       m_ErrorCode = ::GetLastError();
  147.  
  148.       return( FALSE );
  149.    }
  150. }
  151.  
  152. void CNamedPipe::Close( void )
  153. {
  154.    if ( m_PipeHandle != INVALID_HANDLE_VALUE )
  155.    {
  156.       ::CloseHandle( m_PipeHandle );
  157.       m_PipeHandle = INVALID_HANDLE_VALUE;
  158.    }
  159. }
  160.  
  161. BOOL CNamedPipe::Connect( LPOVERLAPPED overlapped_p )
  162. {
  163.    // overlapped_p can be NULL
  164.  
  165.    BOOL return_value = FALSE;
  166.  
  167.    return_value = ::ConnectNamedPipe( m_PipeHandle, overlapped_p );
  168.  
  169.    if ( return_value == TRUE )
  170.    {
  171.       return( TRUE );
  172.    }
  173.    else
  174.    {
  175.       m_ErrorCode = ::GetLastError();
  176.  
  177.       return( FALSE );
  178.    }
  179. }
  180.  
  181. BOOL CNamedPipe::Create( LPCTSTR server_name,
  182.                          LPCTSTR pipe_name,
  183.                          DWORD   open_mode,
  184.                          DWORD   type_of_pipe,
  185.                          DWORD   number_of_pipes,
  186.            LPSECURITY_ATTRIBUTES security_attributes_p )
  187. {
  188.    ASSERT( pipe_name != NULL );
  189.  
  190.    /*
  191.    ** Check parameters for errors
  192.    */
  193.  
  194.    if ( pipe_name == NULL )
  195.    {
  196.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  197.       return( FALSE );
  198.    }
  199.  
  200.    m_PipeName = "\\\\";
  201.  
  202.    if ( server_name == NULL )
  203.    {
  204.       m_PipeName += ".";
  205.    }
  206.    else
  207.    {
  208.       m_PipeName += server_name;
  209.    }
  210.  
  211.    m_PipeName += "\\PIPE\\";
  212.    m_PipeName += pipe_name;
  213.  
  214.    CSecurityAttributes security_attributes;
  215.    SECURITY_DESCRIPTOR security_descriptor;
  216.  
  217.    if ( security_attributes_p == NULL )
  218.    {
  219.       ::InitializeSecurityDescriptor( &security_descriptor, SECURITY_DESCRIPTOR_REVISION );
  220.  
  221.       ::SetSecurityDescriptorDacl( &security_descriptor, TRUE, NULL, FALSE );
  222.       security_attributes.bInheritHandle = FALSE;
  223.       security_attributes.lpSecurityDescriptor = &security_descriptor;
  224.  
  225.       security_attributes_p = (SECURITY_ATTRIBUTES *) &security_attributes;
  226.    }
  227.  
  228.    m_PipeHandle = ::CreateNamedPipe( m_PipeName,
  229.                                      open_mode,
  230.                                      type_of_pipe, 
  231.                                      number_of_pipes,
  232.                                      m_OutputBufferSize,
  233.                                      m_InputBufferSize,
  234.                                      m_Timeout,
  235.                                      security_attributes_p );
  236.  
  237.    if ( m_PipeHandle == INVALID_HANDLE_VALUE )
  238.    {
  239.       m_ErrorCode = ::GetLastError();
  240.       return( FALSE );
  241.    }
  242.    else
  243.    {
  244.       return( TRUE );
  245.    }
  246. }
  247.  
  248. BOOL CNamedPipe::Disconnect( void )
  249. {
  250.    BOOL return_value = FALSE;
  251.  
  252.    return_value = ::DisconnectNamedPipe( m_PipeHandle );
  253.  
  254.    if ( return_value == TRUE )
  255.    {
  256.       return( TRUE );
  257.    }
  258.    else
  259.    {
  260.       m_ErrorCode = ::GetLastError();
  261.  
  262.       return( FALSE );
  263.    }
  264. }
  265.  
  266. BOOL CNamedPipe::GetInformation( void )
  267. {
  268.    BOOL return_value = FALSE;
  269.  
  270.    DWORD type_of_pipe                = 0;
  271.    DWORD size_of_output_buffer       = 0;
  272.    DWORD size_of_input_buffer        = 0;
  273.    DWORD maximum_number_of_instances = 0;
  274.  
  275.    return_value = ::GetNamedPipeInfo( m_PipeHandle,
  276.                                      &type_of_pipe,
  277.                                      &size_of_output_buffer,
  278.                                      &size_of_input_buffer,
  279.                                      &maximum_number_of_instances );
  280.  
  281.    if ( return_value == TRUE )
  282.    {
  283.       return( TRUE );
  284.    }
  285.    else
  286.    {
  287.       m_ErrorCode = ::GetLastError();
  288.  
  289.       return( FALSE );
  290.    }
  291. }
  292.  
  293. BOOL CNamedPipe::GetState( void )
  294. {
  295.    BOOL return_value = FALSE;
  296.  
  297.    TCHAR temp_string[ 513 ];
  298.  
  299.    ::ZeroMemory( temp_string, sizeof( temp_string ) );
  300.  
  301.    return_value = ::GetNamedPipeHandleState( m_PipeHandle,
  302.                                             &m_PipeState,
  303.                                             &m_NumberOfInstances,
  304.                                             &m_MaximumNumberOfBytesBeforeRemoteTransmission,
  305.                                             &m_MaximumNumberOfMillisecondsBeforeRemoteTransmission,
  306.                                              temp_string,
  307.                                              sizeof( temp_string ) );
  308.  
  309.    m_UserNameOfClientProcess = temp_string;
  310.  
  311.    if ( return_value == TRUE )
  312.    {
  313.       return( TRUE );
  314.    }
  315.    else
  316.    {
  317.       m_ErrorCode = ::GetLastError();
  318.  
  319.       return( FALSE );
  320.    }
  321. }
  322.  
  323. BOOL CNamedPipe::Open( const char *pipe_name, UINT port_number, CFileException * perror )
  324. {
  325.    ASSERT( pipe_name != NULL );
  326.  
  327.    if ( pipe_name == (LPCTSTR) NULL )
  328.    {
  329.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  330.  
  331.       return( FALSE );
  332.    }
  333.  
  334.    /*
  335.    ** pipe_name can be:
  336.    ** "pipe_name" where the pipe will be openend on the local machine
  337.    ** "\\server_name\pipe_name" where the pipe will be opened on the server
  338.    ** "\\server_name\PIPE\pipe_name" which is a fully qualified pipe name
  339.    */
  340.  
  341.    CUniversalNamingConvention unc( pipe_name );
  342.  
  343.    TRACE( "unc is \"%s\"\n", (LPCTSTR) unc );
  344.  
  345.    if ( unc.ServerName.IsEmpty() != FALSE )
  346.    {
  347.       unc.ServerName = ".";
  348.    }
  349.  
  350.    if ( unc.ShareName.CompareNoCase( "PIPE" ) != 0 )
  351.    {
  352.       CString temp_string = unc.ShareName;
  353.  
  354.       unc.ShareName = "PIPE";
  355.  
  356.       if ( temp_string.IsEmpty() != TRUE )
  357.       {
  358.          unc.PathName  = temp_string + "\\" + unc.PathName;
  359.       }
  360.    }
  361.  
  362.    unc.Make();
  363.  
  364.    m_FullPipeName = unc;
  365.  
  366.    TRACE( "Full Pipe Name is \"%s\"\n", (LPCTSTR) unc );
  367.  
  368.    return( Create( unc.ServerName, unc.PathName ) );
  369. }
  370.  
  371. BOOL CNamedPipe::Peek( LPVOID buffer_address, 
  372.                        DWORD  size_of_buffer,
  373.                        DWORD& number_of_bytes_read,
  374.                        DWORD& number_of_bytes_available,
  375.                        DWORD& number_of_bytes_remaining_in_message )
  376. {
  377.    /*
  378.    ** buffer_address can be NULL
  379.    */
  380.  
  381.    BOOL return_value = FALSE;
  382.  
  383.    return_value = ::PeekNamedPipe( m_PipeHandle, 
  384.                                    buffer_address, 
  385.                                    size_of_buffer, 
  386.                                   &number_of_bytes_read,
  387.                                   &number_of_bytes_available,
  388.                                   &number_of_bytes_remaining_in_message );
  389.  
  390.    if ( return_value == TRUE )
  391.    {
  392.       return( TRUE );
  393.    }
  394.    else
  395.    {
  396.       m_ErrorCode = ::GetLastError();
  397.  
  398.       return( FALSE );
  399.    }
  400. }
  401.  
  402. BOOL CNamedPipe::SetState( DWORD new_pipe_mode, 
  403.                            DWORD maximum_number_of_bytes_before_transmission, 
  404.                            DWORD maximum_number_of_milliseconds_before_transmission )
  405. {
  406.    BOOL return_value = FALSE;
  407.  
  408.    return_value = ::SetNamedPipeHandleState( m_PipeHandle,
  409.                                             &new_pipe_mode,
  410.                                             &maximum_number_of_bytes_before_transmission,
  411.                                             &maximum_number_of_milliseconds_before_transmission );
  412.  
  413.    if ( return_value == TRUE )
  414.    {
  415.       return( TRUE );
  416.    }
  417.    else
  418.    {
  419.       m_ErrorCode = ::GetLastError();
  420.  
  421.       return( FALSE );
  422.    }
  423. }
  424.  
  425. BOOL CNamedPipe::Transact( LPOVERLAPPED overlapped_p )
  426. {
  427.    // overlapped_p can be NULL
  428.  
  429.    BOOL return_value = FALSE;
  430.  
  431.    return_value = ::TransactNamedPipe( m_PipeHandle,
  432.                                        m_OutputBuffer,
  433.                                        m_NumberOfBytesToWrite,
  434.                                        m_InputBuffer,
  435.                                        m_InputBufferSize,
  436.                                       &m_NumberOfBytesRead,
  437.                                        overlapped_p );
  438.  
  439.    if ( return_value == TRUE )
  440.    {
  441.       return( TRUE );
  442.    }
  443.    else
  444.    {
  445.       m_ErrorCode = ::GetLastError();
  446.  
  447.       return( FALSE );
  448.    }
  449. }
  450.  
  451. BOOL CNamedPipe::Wait( LPCTSTR name_of_server, LPCTSTR name_of_pipe, DWORD number_of_milliseconds )
  452. {
  453.    ASSERT( name_of_pipe != NULL );
  454.  
  455.    /*
  456.    ** Check parameters for errors
  457.    */
  458.  
  459.    if ( name_of_pipe == NULL )
  460.    {
  461.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  462.       return( FALSE );
  463.    }
  464.  
  465.    BOOL return_value = FALSE;
  466.  
  467.    CString full_pipe_name( "\\\\" ); // like \\servername\pipe\pipename
  468.  
  469.    if ( name_of_server == NULL )
  470.    {
  471.       full_pipe_name += ".";
  472.    }
  473.    else
  474.    {
  475.       full_pipe_name += name_of_server;
  476.    }
  477.  
  478.    full_pipe_name += "\\pipe\\";
  479.    full_pipe_name += name_of_pipe;
  480.  
  481.    return_value = ::WaitNamedPipe( full_pipe_name, number_of_milliseconds );
  482.  
  483.    if ( return_value == TRUE )
  484.    {
  485.       return( TRUE );
  486.    }
  487.    else
  488.    {
  489.       m_ErrorCode = ::GetLastError();
  490.  
  491.       return( FALSE );
  492.    }
  493. }
  494.